﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using HasuSLLib;
using System.Collections;
using System.Windows.Threading;
using System.Windows.Resources;
using System.IO;

namespace HasuSLUI
{
    /// <summary>
    /// provide default Control list
    /// </summary>
    public static class UIDefaults
    {
        #region Static Constructor to register default controls
        /// <summary>
        /// use for register control, type, (OnDataBinding & OnCreateControl delegates)
        /// </summary>
        static UIDefaults()
        {
            loadXmlStyle();

            registerDefaultControls();

            registerDefaultColumns();

            registerDefaultValueConverters();
        }

        #endregion

        #region RegisterdControls collection

        private static Dictionary<Type, RegisterdControl> _registerdControls = new Dictionary<Type, RegisterdControl>();

        /// <summary>
        /// RegisterdControls collection
        /// </summary>
        public static Dictionary<Type, RegisterdControl> RegisterdControls
        {
            get { return _registerdControls; }
            set { _registerdControls = value; }
        }

        #endregion

        #region IsRegister to check wather control IsRegisterdControl
        /// <summary>
        /// to check wather control IsRegisterdControl
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsRegisterdControl(Type type)
        {
            return RegisterdControls.ContainsKey(type);
        }
        #endregion

        #region Register default controls

        private static void registerDefaultControls()
        {
            #region Register Textbox control for string type

            RegisterdControls.Add(typeof(string),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 200,
                    BindingProperty = TextBox.TextProperty
                });

            #endregion

            #region Register Textbox control for int type
            RegisterdControls.Add(typeof(int),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 50,
                    BindingProperty = TextBox.TextProperty
                });

            #endregion

            #region Register Textbox control for Int16 type

            RegisterdControls.Add(typeof(Int16),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 50,
                    BindingProperty = TextBox.TextProperty
                });

            #endregion

            #region Register Textbox control for long type

            RegisterdControls.Add(typeof(long),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 80,
                    BindingProperty = TextBox.TextProperty
                });

            #endregion

            #region Register Textbox control for double type

            RegisterdControls.Add(typeof(double),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 80,
                    BindingProperty = TextBox.TextProperty
                });


            #endregion

            #region Register Textbox control for decimal type

            RegisterdControls.Add(typeof(decimal),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 80,
                    BindingProperty = TextBox.TextProperty
                });


            #endregion

            #region Register Textbox control for float type

            RegisterdControls.Add(typeof(float),
                new RegisterdControl()
                {
                    ControlType = typeof(TextBox),
                    DefaultWidth = 100,
                    BindingProperty = TextBox.TextProperty
                });


            #endregion

            #region Register CheckBox control for bool type

            RegisterdControls.Add(typeof(bool),
                new RegisterdControl()
                {
                    ControlType = typeof(CheckBox),
                    DefaultWidth = 50,
                    BindingProperty = CheckBox.IsCheckedProperty
                });

            #endregion

            #region Register Textbox DatePicker for DateTime type

            RegisterdControls.Add(typeof(DateTime),
                new RegisterdControl()
                {
                    ControlType = typeof(HasuSLDatePicker), //DatePicker
                    DefaultWidth = 150,
                    BindingProperty = DatePicker.SelectedDateProperty
                });

            #endregion

            #region Register DatePicker control for Date type

            RegisterdControls.Add(typeof(Date),
                new RegisterdControl()
                {
                    ControlType = typeof(HasuSLDatePicker), //DatePicker
                    DefaultWidth = 120,
                    BindingProperty = DatePicker.TextProperty //DatePicker.SelectedDateProperty
                });

            #endregion

            #region Register ListBox control for IEnumerable

            RegisterdControls.Add(typeof(IEnumerable),
                new RegisterdControl()
                {
                    ControlType = typeof(ListBox),
                    DefaultWidth = 100,
                    BindingProperty = ListBox.ItemsSourceProperty
                });


            #endregion

            #region Register ComboBox control for Lookup type

            RegisterdControls.Add(typeof(Lookup),
                new RegisterdControl()
                {
                    ControlType = typeof(ComboBox),
                    DefaultWidth = 100,
                    BindingProperty = ComboBox.SelectedItemProperty,
                    OnDataBinding = delegate(Control control, object value)
                    {
                        if (control is ComboBox && value is Lookup)
                        {
                            ComboBox tmpCombo = (control as ComboBox);
                            tmpCombo.DisplayMemberPath = "Description";
                            tmpCombo.ItemsSource = (value as Lookup).GetValidList();
                            tmpCombo.SelectedItem = (value as Lookup);
                        }
                    }
                });

            #endregion

            #region Register ComboBox control for Enum

            RegisterdControls.Add(typeof(Enum),
                new RegisterdControl()
                {
                    ControlType = typeof(ComboBox),
                    DefaultWidth = 100,
                    BindingProperty = ComboBox.SelectedItemProperty,
                    OnDataBinding = delegate(Control control, object value)
                    {
                        if (control is ComboBox && value.GetType().IsEnum)
                        {
                            ComboBox tmpCombo = (control as ComboBox);
                            tmpCombo.DisplayMemberPath = "Key";
                            Dictionary<string, object> enumList = Utility.OtherExtra.GetEnumCollection(value.GetType());
                            tmpCombo.ItemsSource = enumList;                          

                            if (enumList != null && enumList.Count > 0)
                            {
                                var selectedVals = from sval in enumList
                                                   where sval.Key == value.ToString()
                                                   select sval;
                                if (selectedVals != null)
                                {
                                    tmpCombo.SelectedItem = selectedVals.FirstOrDefault();
                                }
                            }
                        }
                    }
                });

            #endregion

            #region Register MetaGrid control for ICollection

            RegisterdControls.Add(typeof(ICollection),
                new RegisterdControl()
                {
                    ControlType = typeof(MetaGrid),
                    DefaultWidth = 300,
                    DefaultHeight = 100,
                    BindingProperty = MetaGrid.DataContextProperty,
                    OnDataBinding = delegate(Control control, object value)
                    {
                        if (control is MetaGrid)
                        {
                            (control as MetaGrid).DataContext = value;
                        }
                    }
                });

            #endregion

        }

        #endregion

        #region Default Metadata Provider

        private static IMetadataProvider _defaultMetadataProvider = new MetadataProvider();

        /// <summary>
        /// DefaultMetadataProvider
        /// </summary>
        public static IMetadataProvider DefaultMetadataProvider
        {
            get { return _defaultMetadataProvider; }
            set {
                if (value == null)
                { throw new NullReferenceException("DefaultMetadataProvider can not be null"); }

                _defaultMetadataProvider = value; 
            }
        }

        #endregion Default Metadata Provider

        #region Default Control Factory

        private static IControlFactory _defaultControlFactory = new ControlFactory();  

        /// <summary>
        /// DefaultControlFactory
        /// </summary>
        public static IControlFactory DefaultControlFactory
        {
            get { return _defaultControlFactory; }
            set 
            {
                if (value == null)
                { throw new NullReferenceException("DefaultControlFactory can not be null"); }

                _defaultControlFactory = value; 
            }
        }

        #endregion Default Control Factory 

        #region DefaultGroupPanel

        private static GroupPanel _defaultGroupPanel = new GroupPanel();

        /// <summary>
        /// DefaultGroupPanel to create dynamic clone copy
        /// </summary>
        public static GroupPanel DefaultGroupPanel
        {
            get { return _defaultGroupPanel; }
            set 
            {
                if (value == null)
                { throw new NullReferenceException("DefaultGroupPanel can not be null"); }

                _defaultGroupPanel = value; 
            }
        }

        internal static GroupPanel CreateGroupPanel()
        {
            Object objRet= Activator.CreateInstance(_defaultGroupPanel.GetType());
            /*
            try
            {
                HasuSLLib.Utility.SLExtensions.clone(_defaultGroupPanel, objRet);
            }
            catch (Exception ex)
            {}
            */
            //_defaultGroupPanel.GetType().Assembly.GetManifestResourceStream( 
            return objRet as GroupPanel;
        }

        #endregion DefaultGroupPanel 
        
        #region DefaultMetaControl
        
        private static MetaControl _defaultMetaControl = new  MetaControl();
        
        /// <summary>
        /// DefaultMetaControl
        /// </summary>
        public static MetaControl DefaultMetaControl
        {
            get { return _defaultMetaControl; }
            set 
            {
                if (value == null)
                { throw new NullReferenceException("DefaultMetaControl can not be null"); }

                _defaultMetaControl = value; 
            }
        }

        internal static MetaControl CreateMetaControl()
        {
            Object retMetaCont = Activator.CreateInstance(_defaultMetaControl.GetType());

            /*
            try
            {
                HasuSLLib.Utility.SLExtensions.clone(_defaultMetaControl, objRet);
            }
            catch (Exception ex)
            { }
            */

            return retMetaCont as MetaControl;
        }

        #endregion DefaultMetaControl 	

        #region Default Label Control

        private static TextBlock _defaultLabelControl = new TextBlock();

        /// <summary>
        /// DefaultMetaControl
        /// </summary>
        public static TextBlock DefaultLabelControl
        {
            get { return _defaultLabelControl; }
            set
            {
                if (value == null)
                { throw new NullReferenceException("DefaultLabelControl can not be null"); }

                _defaultLabelControl = value;
            }
        }

        internal static TextBlock CreateLabelControl()
        {
            Object retTxt = Activator.CreateInstance(_defaultLabelControl.GetType());

            /*
            try
            {
                HasuSLLib.Utility.SLExtensions.clone(_defaultLabelControl, retTxt);
            }
            catch (Exception ex)
            { }
            */

            return retTxt as TextBlock;
        }

        #endregion DefaultMetaControl 	


        #region Grid Registerd Columns collection

        private static Dictionary<Type, RegisterdColumn> _registerdColumns = new Dictionary<Type, RegisterdColumn>();

        /// <summary>
        /// Registerd Columns collection
        /// </summary>
        public static Dictionary<Type, RegisterdColumn> RegisterdColumns
        {
            get { return _registerdColumns; }
            set { _registerdColumns = value; }
        }

        public static bool IsRegisterdColumn(Type type)
        {
            return RegisterdColumns.ContainsKey(type);
        }


        private static  void registerDefaultColumns()
        {
            #region Register DataGridTextColumn Columns for string type

            RegisterdColumns.Add(typeof(string),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 100
                });

            #endregion

            #region Register DataGridTextColumn Columns for int type
            RegisterdColumns.Add(typeof(int),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 50
                });

            #endregion

            #region Register DataGridTextColumn Columns for Int16 type

            RegisterdColumns.Add(typeof(Int16),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 50
                });

            #endregion

            #region Register DataGridTextColumn Columns for long type

            RegisterdColumns.Add(typeof(long),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 80
                });

            #endregion

            #region Register DataGridTextColumn Columns for double type

            RegisterdColumns.Add(typeof(double),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 80
                });


            #endregion

            #region Register DataGridTextColumn Columns for decimal type

            RegisterdColumns.Add(typeof(decimal),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 80
                });


            #endregion

            #region Register DataGridTextColumn Columns for float type

            RegisterdColumns.Add(typeof(float),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTextColumn),
                    DefaultWidth = 100
                });


            #endregion

            #region Register DataGridCheckBoxColumn  Column  for bool type

            RegisterdColumns.Add(typeof(bool),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridCheckBoxColumn),
                    DefaultWidth = 50
                });
           
            #endregion

            #region Register DatePicker control for Date type

            RegisterdColumns.Add(typeof(Date),
                new RegisterdColumn()
                {
                    ColumnType = typeof(DataGridTemplateColumn),
                    DefaultWidth = 120
                });

            #endregion

        }

        #endregion

        #region ValueConverter defaults

        private static Dictionary<Type, ValueConverter> _valueConverters = new Dictionary<Type, ValueConverter>();

        /// <summary>
        /// Registerd Columns collection
        /// </summary>
        public static Dictionary<Type, ValueConverter> ValueConverters
        {
            get { return _valueConverters; }
            set { _valueConverters = value; }
        }

        public static bool IsRegisterdValueConverter(Type type)
        {
            return ValueConverters.ContainsKey(type);
        }


        private static void registerDefaultValueConverters()
        {
            #region date value binder

            ValueConverters.Add(typeof(Date),
                new ValueConverter()
                {
                    ConvertTo = delegate(object value, Type targetType)
                    {
                        if (targetType == typeof(string))
                        {
                            return value.ToString();
                        }
                        else
                        {
                            return value;
                        }
                    },
                    ConvertBack = delegate(object value, Type targetType) 
                    {
                        return new Date() { Value = DateTime.Parse(value.ToString()) };
                    }
                    
                });

            #endregion

            #region datetime value binder

            ValueConverters.Add(typeof(DateTime),
                new ValueConverter()
                {
                    ConvertTo = delegate(object value, Type targetType)
                    {
                        if (targetType == typeof(string))
                        {
                            return value.ToString();
                        }
                        if (targetType ==  typeof( System.Nullable<DateTime>))
                        {
                            System.Nullable<DateTime> nlDt= DateTime.Parse(value.ToString());
                            return nlDt;
                        }
                        else
                        {
                            return value;
                        }
                    },
                    ConvertBack = delegate(object value, Type targetType)
                    {
                        return  DateTime.Parse(value.ToString()) ;
                    }

                });

            #endregion

            #region enum value binder

            ValueConverters.Add(typeof(Enum),
                new ValueConverter()
                {
                    ConvertTo = delegate(object value, Type targetType)
                    {
                        if (targetType == typeof(object))
                        {
                            return value;
                        } 
                        else if (targetType.IsEnum )
                        {
                            KeyValuePair<string, object> tmpvalue = (KeyValuePair<string, object>) value ;
                            return Enum.Parse(targetType, tmpvalue.Key, true);
                        }
                        else
                        {
                            return value;
                        }
                    },
                    ConvertBack = delegate(object value, Type targetType)
                    {
                        if (targetType.IsEnum)
                        {
                            KeyValuePair<string, object> tmpvalue = (KeyValuePair<string, object>)value;
                            return Enum.Parse(targetType, tmpvalue.Key, true);
                        }
                        else
                        {
                            return value;
                        }
                    }

                });

            #endregion

            #region Lookup value binder

            ValueConverters.Add(typeof(Lookup),
                new ValueConverter()
                {
                    ConvertTo = delegate(object value, Type targetType)
                    {
                        if (targetType == typeof(object))
                        {
                            return value;
                        } 
                        else
                        {
                            return value;
                        }
                    },
                    ConvertBack = delegate(object value, Type targetType)
                    {
                        if (targetType.IsEnum)
                        {
                            KeyValuePair<string, object> tmpvalue = (KeyValuePair<string, object>)value;
                            return Enum.Parse(targetType, tmpvalue.Key, true);
                        }
                        else
                        {
                            return value;
                        }
                    }

                });

            #endregion

        }

        #endregion


        #region Get the Default Margin

        public static int Margin = 2;

        /// <summary>
        /// Gets the default margin.
        /// </summary>
        /// <returns></returns>
        public static Thickness GetMargin()
        {
            return new Thickness(Margin);
        }

        #endregion

        #region private methods

        private static  void loadXmlStyle()
        {
            Uri uri = new Uri("metaStyles.xml", UriKind.Relative);
            StreamResourceInfo streamInfo = Application.GetResourceStream(uri);
            if (streamInfo != null && streamInfo.Stream != null)
            {
                using (StreamReader reader = new StreamReader(streamInfo.Stream) )
                {
                    Style style = (Style)System.Windows.Markup.XamlReader.Load(reader.ReadToEnd());
                }
            }
 
        }

        #endregion
    }
}
